import { Component, OnInit, OnDestroy } from '@angular/core'
import { Router, ActivatedRoute, Params } from '@angular/router'
import { take } from 'rxjs/operators'
import { NzMessageService } from 'ng-zorro-antd'
import { ACLService, ACLCanType } from '@delon/acl'
import { I18NService } from '@core/i18n/i18n.service'
import { IBaseInfoColumn } from '@shared/interfaces/baseInfo'
import { TradeService } from '../trade-abstract.service'
import { DetailBaseClass } from '@shared/classes/DetailBaseClass'
import { ITrade, ECategoryUrl, ERevFlag, ETransType, EProcFlag, ECategory } from '@shared/interfaces/trade'
import { PageService } from '@shared/services/page.service'
import { ETradeChannel, TransProcI18n, ETransScene, ECustomAcl } from '@shared/enums'
import { DataService } from '@shared/services/data.service'
import { AmtFormatPipe } from '@shared/filters/amt-format.pipe'
import { I18NPrefixWithPipe } from '@shared/filters/i18n-prefix-with.pipe'
import { signAmtNumberOfTrade, getLocalTime } from 'app/utils/helpers'
import { ModalService } from '@shared/services/modal.service'
import { TradeSettStatusTextMap } from '@shared/interfaces/common'
import { CustomACLService } from '@shared/services/acl.service'
import * as dayjs from 'dayjs'

@Component({
  selector: 'app-trades-detail',
  templateUrl: './detail.component.html',
})
export class TradesDetailComponent extends DetailBaseClass<ITrade> implements OnInit, OnDestroy {
  firstColumns: IBaseInfoColumn[]
  secondColumns: IBaseInfoColumn[]
  thirdColumns: IBaseInfoColumn[]
  fourthColumns: IBaseInfoColumn[]

  acquirerColumns: IBaseInfoColumn[]
  groupColumns: IBaseInfoColumn[]
  merchantColumns: IBaseInfoColumn[]
  storeColumns: IBaseInfoColumn[]
  terminalColumns: IBaseInfoColumn[]
  ECategory = ECategory
  /** 只有正向成功交易才显示 */
  isShowRefund = false
  /** 只有未清算的交易才展示 */
  isShowMerRefund = false
  isShowPresent = false
  isShowManualVoid = false
  isManualsettled = false     // 是否已手工请款
  isCheckTransScence = false
  isCheckRefund = false       // 手工退款
  isCheckAth = true           // web-ATH的标志
  category: string
  TradeSettStatusTextMap = TradeSettStatusTextMap
  constructor(
    public msg: NzMessageService,
    public i18n: I18NService,
    public router: Router,
    public route: ActivatedRoute,
    public tradeService: TradeService,
    public pageService: PageService,
    private aclService: ACLService,
    private dataService: DataService,
    private i18nPrefixWithPipe: I18NPrefixWithPipe,
    private amtFormatPipe: AmtFormatPipe,
    public modalService: ModalService,
    private customACLService: CustomACLService,
  ) {
    super(pageService)
  }

  ngOnInit(): void {
    this.route.params.subscribe((params: Params) => {
      this.category = params['category'] as string
      if (this.category === ECategory.Card) {
        this.customACLService.addACLAbility(ECustomAcl.Present)
      }
      this.initData(params)
      this.isManualsettled = this.detailData.isManualsettled ? false : true
    })
  }

  ngOnDestroy(): void {
    this.dataService.resetTrade()
    this.customACLService.removeACLAbility(ECustomAcl.Present)
  }

  initData(params: Params): void {
    const orderNum = params['orderNum']
    const intStoreCode = params['intStoreCode']
    const category = params['category'] as string
    this.loading = true
    this.tradeService
      .getOne({ orderNum, intStoreCode }, ECategoryUrl[category])
      .pipe(take(1))
      .subscribe(res => {
        this.renderTrade(res)
      })
  }

  renderTrade(trade: ITrade): void {
    this.detailData = trade
    this.checkIsShowRefund()
    this.checkIsShowPresent()
    this.checkIsShowManualVoid()
    this.initFirstColumns()
    this.initSecondColumns()
    this.initThirdColumns()
    this.initFourthColumns()
    this.initAcquirerColumns()
    this.initGroupColumns()
    this.initMerchantColumns()
    this.initStoreColumns()
    this.initColumns()
    this.loading = false
    this.dataService.setTrade(trade)
  }

  checkIsShowRefund(): void {
    if (this.category === ECategory.Card) {
      this.isShowRefund =
        this.detailData.procFlag === EProcFlag.ProcSuccess &&
        (this.detailData.revFlag === ERevFlag.RevNormal || this.detailData.revFlag === ERevFlag.RevPartRefunded)
          ? true
          : false
    } else {
      this.isShowRefund =
        this.detailData.transType === ETransType.PayTrans &&
        this.detailData.procFlag === EProcFlag.ProcSuccess &&
        (this.detailData.revFlag === ERevFlag.RevNormal || this.detailData.revFlag === ERevFlag.RevPartRefunded)
          ? true
          : false
    }
    this.isCheckRefund = this.returnTransScenceCheck(this.detailData.transScene)
    this.isCheckAth = this.detailData.transScene === 'web-ATH' ? false : true
    this.isShowMerRefund =
      this.detailData.transType === ETransType.PayTrans &&
      this.detailData.procFlag === EProcFlag.ProcSuccess &&
      (this.detailData.revFlag === ERevFlag.RevNormal || this.detailData.revFlag === ERevFlag.RevPartRefunded)
        ? true
        : false
  }

  checkIsShowPresent(): void {
    this.isShowPresent =
      this.detailData.procFlag === EProcFlag.ProcSuccess &&
      (this.detailData.revFlag === ERevFlag.RevNormal ||
        this.detailData.revFlag === ERevFlag.RevPartRefunded ||
        this.detailData.revFlag === ERevFlag.AdjustAmt ||
        this.detailData.revFlag === ERevFlag.RevRefunded) &&
      !this.detailData.settFlag
        ? true
        : false
    this.isManualsettled = this.detailData.isManualsettled ? false : true
    this.isCheckTransScence =
      this.transScenceCheck(this.detailData.transScene) && this.detailData.procFlag === EProcFlag.ProcSuccess
  }

  checkIsShowManualVoid(): void {
    const { settFlag, transScene, revFlag, procFlag, createdAt } = this.detailData
    // 交易时间在当天且在22:00以前
    const checkTime = dayjs(createdAt).isSame(getLocalTime(7), 'day') &&
    dayjs(getLocalTime(7)).isBefore(
      dayjs(getLocalTime(7))
        .set('hour', 22)
        .set('minute', 0)
        .set('second', 0)
        .set('millisecond', 0)
    ) && dayjs(createdAt).isBefore(
      dayjs(getLocalTime(7))
        .set('hour', 22)
        .set('minute', 0)
        .set('second', 0)
        .set('millisecond', 0)
    )
    this.isShowManualVoid =
      this.voidTransScenceCheck(transScene) &&
      !settFlag &&
      checkTime &&
      procFlag === EProcFlag.ProcSuccess &&
      (revFlag === ERevFlag.RevNormal ||
       revFlag === ERevFlag.RevPartRefunded ||
       revFlag === ERevFlag.AdjustAmt)

  }

  initFirstColumns(): void {
    const { currency } = this.detailData
    const transAmt = this.computeTransAmt(this.detailData)
    this.firstColumns = [
      {
        span: 8,
        index: 'createdAt',
        label: 'TRADE.TRANS_TIME',
        labelI18n: 'TRADE.TRANS_TIME',
        type: 'date',
      },
      {
        span: 8,
        index: 'orderNum',
        label: 'TRADE.ORDER_NUM',
        labelI18n: 'TRADE.ORDER_NUM',
      },
      {
        span: 4,
        index: 'transAmt',
        label: 'TRADE.TRANS_AMT',
        labelI18n: 'TRADE.TRANS_AMT',
        asyncValue: this.amtFormatPipe.transform(transAmt, currency),
      },
      {
        span: 4,
        index: 'terminalid',
        label: 'GENERAL.TERMINAL.CODE',
        labelI18n: 'GENERAL.TERMINAL.CODE',
      },
    ]
  }

  initSecondColumns(): void {
    this.secondColumns = [
      {
        span: 8,
        index: 'paymentBrand',
        label: 'GENERAL.INFO.CHANNEL',
        labelI18n: 'GENERAL.INFO.CHANNEL',
        pipe: this.parsePaymentBrand.bind(this),
      },
      {
        span: 8,
        index: 'transScene',
        label: 'TRADE.TRANS_SCENE',
        labelI18n: 'TRADE.TRANS_SCENE',
        pipe: this.parseTransScene.bind(this),
      },
      {
        span: 8,
        index: 'procFlag',
        label: 'GENERAL.INFO.STATUS',
        labelI18n: 'GENERAL.INFO.STATUS',
        pipe: this.parseProcFlag.bind(this),
      },
    ]
  }

  initThirdColumns(): void {
    this.thirdColumns = [
      {
        span: 8,
        index: 'acctNumSensitive',
        label: 'TRADE.CARD_NUMBER',
        labelI18n: 'TRADE.CARD_NUMBER',
      },
      {
        span: 8,
        index: 'authCode',
        label: 'TRADE.AUTH_CODE',
        labelI18n: 'TRADE.AUTH_CODE',
      },
      {
        span: 8,
        index: 'retrievalRefNum',
        label: 'TRADE.RRN',
        labelI18n: 'OPERATION.TRADE.RETRIEVAL_REFNUM',
      },
    ]
  }

  initFourthColumns(): void {
    this.fourthColumns = [
      {
        span: 8,
        index: 'termTraceNum',
        label: 'TRADE.SERIALNUM',
        labelI18n: 'TRADE.SERIALNUM',
      },
      {
        span: 8,
        index: 'batchNum',
        label: 'TRADE.BATCHNUM',
        labelI18n: 'TRADE.BATCHNUM',
      },
      {
        span: 8,
        index: 'settFlag',
        label: 'TRADE.SETTLE.STATUS',
        labelI18n: 'TRADE.SETTLE.STATUS',
        acl: [ECustomAcl.Present],
        displayValue: this.trans(this.detailData.settFlag ? 'TRADE.SETTLE.SETTLED' : 'TRADE.SETTLE.UNSETTLED'),
      },
    ]
  }

  initAcquirerColumns(): void {
    this.acquirerColumns = [
      {
        span: 8,
        index: 'insCode',
        label: 'GENERAL.INSTITUTION.CODE',
        labelI18n: 'GENERAL.INSTITUTION.CODE',
      },
      {
        span: 8,
        index: 'insName',
        label: 'GENERAL.INSTITUTION.NAME',
        labelI18n: 'GENERAL.INSTITUTION.NAME',
      },
      {
        span: 8,
        index: 'insNameEN',
        label: 'GENERAL.INSTITUTION.NAME_EN',
        labelI18n: 'GENERAL.INSTITUTION.NAME_EN',
      },
    ]
  }

  initGroupColumns(): void {
    this.groupColumns = [
      {
        span: 8,
        index: 'agentCode',
        label: 'GENERAL.AGENT.CODE',
        labelI18n: 'GENERAL.AGENT.CODE',
      },
      {
        span: 8,
        index: 'agentName',
        label: 'GENERAL.AGENT.NAME',
        labelI18n: 'GENERAL.AGENT.NAME',
      },
      {
        span: 8,
        index: 'agentNameEN',
        label: 'GENERAL.AGENT.NAME_EN',
        labelI18n: 'GENERAL.AGENT.NAME_EN',
      },
    ]
  }

  initMerchantColumns(): void {
    this.merchantColumns = [
      {
        span: 8,
        index: 'merNum',
        label: 'GENERAL.MERCHANT.NUM',
        labelI18n: 'GENERAL.MERCHANT.NUM',
      },
      {
        span: 8,
        index: 'merName',
        label: 'GENERAL.MERCHANT.NAME',
        labelI18n: 'GENERAL.MERCHANT.NAME',
      },
      {
        span: 8,
        index: 'merNameEN',
        label: 'GENERAL.MERCHANT.NAME_EN',
        labelI18n: 'GENERAL.MERCHANT.NAME_EN',
      },
    ]
  }

  initStoreColumns(): void {
    this.storeColumns = [
      {
        span: 8,
        index: 'storeNum',
        label: 'GENERAL.STORE.NUM',
        labelI18n: 'GENERAL.STORE.NUM',
      },
      {
        span: 8,
        index: 'storeName',
        label: 'GENERAL.STORE.NAME',
        labelI18n: 'GENERAL.STORE.NAME',
      },
      {
        span: 8,
        index: 'storeNameEN',
        label: 'GENERAL.STORE.NAME_EN',
        labelI18n: 'GENERAL.STORE.NAME_EN',
      },
    ]
  }

  initColumns(): void {
    this.initValue.call(this, this.firstColumns)
    this.initValue.call(this, this.secondColumns)
    this.initValue.call(this, this.thirdColumns)
    this.initValue.call(this, this.fourthColumns)
    this.initValue.call(this, this.acquirerColumns)
    this.initValue.call(this, this.groupColumns)
    this.initValue.call(this, this.merchantColumns)
    this.initValue.call(this, this.storeColumns)
  }

  parsePaymentBrand(paymentBrand: string): string {
    return this.trans(ETradeChannel[paymentBrand])
  }

  parseTransScene(transScene: string): string {
    try {
      return this.trans(ETransScene[transScene])
    } catch (e) {
      return this.trans('GENERAL.INFO.NONE')
    }
  }

  parseProcFlag(procFlag: string): string {
    return this.trans(TransProcI18n[procFlag])
  }

  trans(str: string): string {
    if (!str) {
      return ''
    }

    return this.i18n.fanyi(str)
  }

  goRefund(): void {
    const url = this.router.url
    const originUrl = url.split(';')[0]
    this.router.navigateByUrl(`${originUrl}/refund`)
  }

  goManualRefund(): void {
    const url = this.router.url
    const originUrl = url.split(';')[0]
    this.router.navigateByUrl(`${originUrl}/manualRefund`)
  }

  goManualPresent(): void {
    const url = this.router.url
    const originUrl = url.split(';')[0]
    this.router.navigateByUrl(`${originUrl}/manualPresent`)
  }

  goManualVoid(): void {
    this.modalService.delete(this.trans('GENERAL.NOTIFICATION.VOID_ORDER_CONFIRM')).subscribe(isOk => {
      if (!isOk) {
        return
      }
      const { insCode, intStoreCode, orderNum } = this.detailData
      this.tradeService.manualVoid({insCode, intStoreCode, orderNum})
      .pipe(take(1))
      .subscribe(() => this.voidSuccess(), err => this.voidFail())
    })
  }
  /** 商户退款按钮 */
  computeIsShowRefundButton(): boolean {
    const canRefund: ACLCanType = {
      ability: ['api.post.camel.trade.rfdp', 'api.post.camel.trade.refd'],
    }
    return this.aclService.canAbility(canRefund) && this.isShowMerRefund && this.isCheckAth
  }
  /** 手工退款按钮 */
  computeIsShowManualRefundButton() {
    const canRefund: ACLCanType = {
      ability: ['api.post.camel.trade.rfdp', 'api.post.camel.trade.refd'],
    }
    if (this.category === ECategory.Card) {
      return this.aclService.canAbility(canRefund) && this.isShowRefund && this.isCheckRefund
    } else if (this.category === ECategory.Qr) {
      return this.aclService.canAbility(canRefund) && this.isShowRefund
    }
  }
  /** 手工请款按钮 */
  computeIsShowPresentButton(): boolean {
    const canPresent: ACLCanType = {
      ability: ['api.post.turtle.trade.manualtrans'],
    }
    return (
      this.aclService.canAbility(canPresent) && this.isShowPresent && this.isManualsettled && this.isCheckTransScence
    )
  }
  /** 手工撤销按钮 */
  computeIsShowManualVoidButton(): boolean {
    const canVoid: ACLCanType = {
      ability: ['api.post.turtle.trade.rvctmanual'],
    }

    return (
      this.aclService.canAbility(canVoid) && this.isShowManualVoid
    )
  }

  computeTransAmt(trade: ITrade): number {
    return signAmtNumberOfTrade(trade)
  }

  // 成功未撤销，冲正，预授权完成，离线预授权完成，退货，MOTO消费，MOTO预授权完成，MOTO离线预授权完成，MOTO退货
  transScenceCheck(transScene: string): boolean {
    const transSceneList = [
      'pos-MER', 'pos-MTH',
      'pos-MCR', 'pos-ACR',
      'pos-CJT', 'pos-CTH',
      'pos-PER', 'web-MER',
      'web-MTH', 'web-MCR'
    ]
    if (transSceneList.indexOf(transScene) !== -1) {
      return true
    }
    return false
  }

  /** 预授权完成 MOTO消费 MOTO预授权完成 离线预授权完成 卡交易 */
  returnTransScenceCheck(transScene: string): boolean {
    const transSceneList = [
      'pos-MER', 'pos-MCR',
      'pos-PER', 'pos-CJT',
      'pos-ACR', 'web-MER',
      'web-MCR'
    ]
    if (transSceneList.indexOf(transScene) !== -1) {
      return true
    }
    return false
  }

  /** 平台的 MOTO预授权、MOTO预授权完成、MOTO消费、MOTO退货  */
  voidTransScenceCheck(transScene: string): boolean {
    const transSceneList = ['web-MPA', 'web-MCR', 'web-MER', 'web-MTH']
    if (transSceneList.indexOf(transScene) !== -1) {
      return true
    }
    return false
  }

  private voidSuccess(): void {
    this.router.navigateByUrl('/trades/list')
  }

  private voidFail(): void {
    this.msg.error(this.trans('TRADE_STATUS.REJECT'))
  }
}
